package service

import (
	"cgs-server/server"
	"cgs-server/server/cgs/notice/models"
	"cgs-server/server/cgs/notice/models/vo"
	"cgs-server/server/model"
	"context"
	"fmt"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"strings"
)

func SaveNotice(userIds string, msg string, noticeType models.NoticeType) {
	ids := strings.Split(userIds, ",")
	notice := models.Notice{Msg: msg}
	notice.ResolveEntity(&notice, nil)
	db, err := server.Mongo()
	if err != nil {
		fmt.Errorf("Get db error: " + err.Error())
		return
	}
	db.InsertOne(server.NoticeCollectionName, notice)
	noticeId := notice.Id
	for _, value := range ids {
		noticeRelation := models.NoticeRelation{
			NoticeType: noticeType,
			NoticeId:   noticeId,
			UserId:     value,
			IsRead:     false,
			IsFav:      false,
		}
		noticeRelation.ResolveEntity(&noticeRelation, nil)
		db.InsertOne(server.NoticeRelationCollectionName, noticeRelation)
		sendNoticeWS(value, notice, noticeType)
	}

}
func SendNoticeApi(userId string, msg string, noticeType models.NoticeType) {
	notice := models.Notice{Msg: msg}
	notice.ResolveEntity(&notice, nil)
	db, err := server.Mongo()
	if err != nil {
		fmt.Errorf("Get db error: " + err.Error())
		return
	}
	db.InsertOne(server.NoticeCollectionName, notice)
	noticeId := notice.Id
	noticeRelation := models.NoticeRelation{
		NoticeType: noticeType,
		NoticeId:   noticeId,
		UserId:     userId,
		IsRead:     false,
		IsFav:      false,
	}
	noticeRelation.ResolveEntity(&noticeRelation, nil)
	db.InsertOne(server.NoticeRelationCollectionName, noticeRelation)
	sendNoticeWS(userId, notice, noticeType)
}

func sendNoticeWS(userId string, notice models.Notice, noticeType models.NoticeType) {
	db, err := server.Mongo()
	if err != nil {
		fmt.Errorf("Get db error: " + err.Error())
		return
	}
	docs := bson.M{}
	tokenFilter := bson.M{
		"UserId": userId,
	}
	find, err := db.FindOne(server.CgsTokenCollectionName, tokenFilter, &docs)
	if find {
		user := server.User{
			Id:    userId,
			Token: "NOT_EXITS_TOKEN",
		}
		notice := bson.M{
			"notice_type": noticeType,
			"msg":         notice.Msg,
			"create_time": notice.CreateTime,
			"user_id":     userId,
		}
		wsMsg := server.BroadcastMessage{
			Type: "send_notice",
			Data: notice,
		}
		server.WebsocketHub.SendByUser(&wsMsg, user)

	}

}
func clearNoticeWS(userId string, noticeType int64) {
	db, err := server.Mongo()
	if err != nil {
		fmt.Errorf("Get db error: " + err.Error())
		return
	}
	docs := bson.M{}
	tokenFilter := bson.M{
		"UserId": userId,
	}
	find, err := db.FindOne(server.CgsTokenCollectionName, tokenFilter, &docs)
	if find {
		user := server.User{
			Id:    userId,
			Token: "NOT_EXITS_TOKEN",
		}
		notice := bson.M{
			"notice_type": noticeType,
			"user_id":     userId,
		}
		wsMsg := server.BroadcastMessage{
			Type: "clear_notice",
			Data: notice,
		}
		server.WebsocketHub.SendByUser(&wsMsg, user)

	}
}
func ListPage(page model.Page, noticeType int64, user *model.User) (result model.PageResult) {
	db, err := server.Mongo()
	if err != nil {
		fmt.Errorf("Get db error: " + err.Error())
		return
	}
	filter := bson.M{
		"user_id": user.UserId.Hex(),
	}
	if noticeType != -1 {
		filter["noticetype"] = noticeType

	}
	mdls := models.NoticeRelation{}
	//mdls.ResolveFilter(&mdls, user, &filter)
	opts1 := mdls.ResolveOptions(&page)
	var results []models.NoticeRelation
	db.FindMany(server.NoticeRelationCollectionName, filter, &results, opts1)
	count, _ := db.Count(server.NoticeRelationCollectionName, filter)
	var ntc []vo.Notice
	for _, v := range results {
		noticeId := v.NoticeId
		filter := bson.M{
			"id": noticeId,
		}
		notice := &models.Notice{}
		find, _ := db.FindOne(server.NoticeCollectionName, filter, &notice)
		vo := vo.Notice{
			NoticeId:   noticeId,
			IsFav:      v.IsFav,
			NoticeType: v.NoticeType,
			CreateTime: v.CreateTime,
			AppId:      v.AppId,
		}
		if find {
			vo.Msg = notice.Msg
		}
		ntc = append(ntc, vo)
	}

	pageResult := model.PageResult{
		Records: ntc,
		Total:   count,
		Size:    page.Size,
	}
	return pageResult
}

func Count(noticeType int64, user *model.User) ([]bson.M, error) {
	db, err := server.Mongo()
	if err != nil {
		fmt.Errorf("Get db error: " + err.Error())
		return nil, err
	}
	filter := bson.D{
		{"$and",
			bson.A{
				bson.D{
					{"user_id", user.UserId.Hex()},
				},
				bson.D{
					{"is_read", false},
				},
			}},
	}
	matchState := bson.D{{"$match", filter}}
	groupState := bson.D{
		{
			"$group", bson.D{
				{"_id", "$noticetype"},
				{"notice_type", bson.D{
					{"$avg", "$noticetype"},
				}},
				{"notice_total", bson.D{
					{"$sum", 1},
				}},
			},
		},
	}
	collection, _ := db.GetCollection(server.NoticeRelationCollectionName)
	cursor, err := collection.Aggregate(context.TODO(), mongo.Pipeline{matchState, groupState})
	if err != nil {
		fmt.Errorf(err.Error())
		return nil, err
	}
	var results []bson.M
	err = cursor.All(context.TODO(), &results)

	return results, err
}

func Clear(noticeType int64, user *model.User) (interface{}, error) {
	db, err := server.Mongo()
	if err != nil {
		fmt.Errorf("Get db error: " + err.Error())
		return nil, err
	}

	filterA := bson.A{
		bson.M{"user_id": user.UserId.Hex()},
		bson.M{"is_read": false},
	}
	if noticeType != -1 {
		filterA = append(filterA, bson.M{
			"noticetype": noticeType})
	}
	filter := bson.M{
		"$and": filterA,
	}

	update := bson.D{
		{"$set", bson.M{
			"is_read": true}},
	}

	updateResult, err := db.UpdateMany(server.NoticeRelationCollectionName, filter, update)
	clearNoticeWS(user.UserId.Hex(), noticeType)
	return updateResult, err
}

func sendNoticeToApp(userId string, notice models.Notice, noticeType models.NoticeType) {

}
